package userHelp

import (
	"common/helper"
	"database/sql"
	"encoding/json"
	"github.com/bytedance/sonic"
	g "github.com/doug-martin/goqu/v9"
	"github.com/jmoiron/sqlx"
	"log"
	"reflect"
	"strconv"
)

const (
	selectType_common = 0

	// 扩展查询的类型
)

type AccountId string

type StTableField struct {
	//查询条件
	selectType int //0

	fieldStruct interface{}
}

type FuncSetRedis func(uid string, field string, strValue string) bool

var g_funcSetFieldRedis FuncSetRedis
var g_mapTableField map[string] /*table name*/ StTableField
var g_sql *sqlx.DB

func getSelectSql(tableName string, fieldInfo *StTableField, uid AccountId) string {
	t := g.Dialect("mysql").From(tableName)
	//todo where条件 g.Ex还没找到比较好的抽象方式
	sqlStr, _, err := t.Select(EnumFields(fieldInfo.fieldStruct)...).Where(g.Ex{"uid": uid}).Limit(1).ToSQL()
	if err != nil {
		helper.SqlSelectErrLog("getSelectSql table name:%s,err%s,", tableName, err.Error(), sqlStr)
	}

	return sqlStr
}

func setToRedis(tableName string, fieldInfo *StTableField, sqlStr string, uid AccountId) {

	sqlDest := SwitchTableStruct(tableName)

	err := g_sql.Get(sqlDest, sqlStr)
	if err != nil && err != sql.ErrNoRows {
		helper.SqlSelectErrLog("setToRedis err,%s,\n %s", err.Error(), sqlStr)
		return
	}

	jsonData, err := sonic.Marshal(sqlDest)
	if err != nil {
		helper.InfoLog("json err:", err)
		return
	}
	//todo 后续换更好的解析方式
	var result map[string]interface{}
	err = json.Unmarshal([]byte(jsonData), &result)

	if err != nil {
		log.Fatalf("json.Unmarshal failed: %v", err)
	}

	for key, value := range result {
		var strVal string
		switch v := value.(type) {
		case string:
			strVal = v
			break
		case int, int8, int16, int32, int64:
			strVal = strconv.FormatInt(reflect.ValueOf(v).Int(), 10)
			break
		case uint, uint8, uint16, uint32, uint64:
			strVal = strconv.FormatUint(reflect.ValueOf(v).Uint(), 10)
			break
		case float32:
			strVal = strconv.FormatFloat(float64(v), 'f', -1, 32)
			break
		case float64:
			strVal = strconv.FormatFloat(v, 'f', -1, 64)
			break
		default:
			helper.InfoLog("setToRedis Unknown type: %s: %v\n", key, v)
		}
		//print("key:", key, " ,strVal:", strVal, "\n")
		//redis.SetUserFieldValue(int32(uid), tableName+":"+key, strVal)
		g_funcSetFieldRedis(string(uid), tableName+":"+key, strVal)
	}

}

func EnumFields(obj interface{}) []interface{} {

	rt := reflect.TypeOf(obj)
	if rt.Kind() != reflect.Struct {
		return nil
	}

	var fields []interface{}
	for i := 0; i < rt.NumField(); i++ {
		f := rt.Field(i)
		if field := f.Tag.Get("db"); field != "" && field != "-" {
			fields = append(fields, field)
		}
	}

	return fields
}
